﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Models;
using Utilities;
using System.Web.Mvc;

namespace BLL
{
    public class FlowRun
    {
        public static bool Start(int workflowid, string[] AllKeys,IValueProvider vp)
        {
            try
            {
                var wi = FlowRun.GenerateWorkflowInstance(workflowid);
                CH.Create<WorkflowInstance>(wi);
                wi.FieldInstances = new List<FieldInstance>();

                var filist = new List<FieldInstance>();
                foreach (var key in AllKeys)
                {
                    var field = CH.GetAllData<Field>(f => f.FieldName == key).FirstOrDefault();

                    if (field != null)
                    {
                        var value = vp.GetValue(key);
                        var fi = new FieldInstance() { FieldValue = value.AttemptedValue, Field = field, FieldID = field.ID, WorkflowInstance = wi, WorkflowInstanceID = wi.ID };
                        filist.Add(fi);
                    }
                }
                CH.EditCollection<FieldInstance>(wi.FieldInstances, filist);

                var orderedactivities = wi.Workflow.Activities.OrderBy(a => a.Sequence).ToList();
                var listai = new List<ActivityInstance>();
                var firstactivity = orderedactivities.FirstOrDefault();
                listai.Add(new ActivityInstance() { Activity = firstactivity, ActivityID = firstactivity.ID, WorkflowInstanceID = wi.ID, WorkflowInstance = wi});
                CH.EditCollection<ActivityInstance>(wi.ActivityInstances, listai);
       
            }
            catch (Exception ex)
            { 
                return false;
            }
            return true;
        }

        public static bool Approve(int id, string[] AllKeys,IValueProvider vp)
        {
            try
            {
                var wi = CH.GetAllData<WorkflowInstance>(i => i.ID == id, "FieldInstances", "ActivityInstances").FirstOrDefault();

                var approveresult = vp.GetValue("app-result").AttemptedValue;

                var ca = wi.ActivityInstances.LastOrDefault();
                ca.Result= approveresult;
                var orderedactivities = wi.Workflow.Activities.OrderBy(a => a.Sequence).ToList();
                Activity nextactivity;
                if (wi.ActivityInstances.Count == 0)
                    nextactivity = orderedactivities.FirstOrDefault();
                else
                    nextactivity = orderedactivities.FirstOrDefault(n => n.Sequence > wi.ActivityInstances.LastOrDefault().Activity.Sequence);

                if (nextactivity != null)
                {
                    var ai = new ActivityInstance() { Activity = nextactivity, ActivityID = nextactivity.ID, WorkflowInstanceID = id };
                    CH.Create<ActivityInstance>(ai);
                }
                else
                {
                    ca.IsEnd = true;
                    
                }
                CH.Edit<ActivityInstance>(ca);
            }
            catch(Exception ex)
            {
                return false;
            }
            return true;
        }

        public static Activity GetNextActivity(WorkflowInstance wi)
        {
            if (wi.ActivityInstances != null)
            {
                var ai = wi.ActivityInstances.LastOrDefault();
                var a = ai.Activity;
                var sortlist = CH.DB.Activities.ToList().OrderBy(aa => aa.Sequence).ToList();
                var next = sortlist.FirstOrDefault(n => n.Sequence > a.Sequence);
                return next;
            }
            else
            {
                var next = CH.DB.Activities.ToList().OrderBy(aa => aa.Sequence).ToList().FirstOrDefault();
                return next;
            }
        }

        public static bool AddNextActivityInstance(WorkflowInstance wi)
        {
            var next = GetNextActivity(wi);
            if (next == null) return false; 
            var ai = new ActivityInstance() {  Activity = next, ActivityID = next.ID };
            if (wi.ActivityInstances == null) wi.ActivityInstances = new List<ActivityInstance>();
            wi.ActivityInstances.Add(ai);
            return true;
           
        }

        public static FieldInstance GetFieldInstance(int? workflowinstanceid,int fieldid)
        {
            return CH.DB.FieldInstances.FirstOrDefault(fi => fi.FieldID == fieldid && fi.WorkflowInstanceID == workflowinstanceid);
        }

        public static string GetFieldInstanceValue(int? workflowinstanceid, int fieldid)
        {
            var fi = GetFieldInstance(workflowinstanceid, fieldid);

            return fi == null?string.Empty:fi.FieldValue ;
        }

        public static WorkflowInstance GenerateWorkflowInstance(int workflowid)
        {
            var wf = CH.GetAllData<Workflow>(w => w.ID == workflowid, "Fields", "Conditions","Participants","Activities","ActivityResults").FirstOrDefault();
           
            if (wf == null) throw new Exception("未能找到匹配");

            wf.Activities = wf.Activities.OrderBy(a => a.Sequence).ToList();
            wf.Fields = wf.Fields.OrderBy(f => f.Sequence).ToList();

            var result = new WorkflowInstance( );
            result.Workflow = wf;
            result.WorkflowID = wf.ID;
            AddNextActivityInstance(result);
         
            return result;

        }

        public static Participant GetParticipants(Activity nextactivity, int id)
        {
            if(nextactivity.Participants == null) throw new ArgumentNullException("");
            foreach (var p in nextactivity.Participants)
            {
                if (IsParticipantSatisfied(p))
                    return p;
            }
            return null;
        }

        public static string GetCurrentApprover(ActivityInstance ai)
        {
            var p = CH.GetAllData<Activity>(a => a.ID == ai.ActivityID, "Participants").FirstOrDefault().Participants.FirstOrDefault();
            return p.Employees.FirstOrDefault().FullName;
           
 
        }

        public static bool IsParticipantSatisfied(Participant p)
        {
            return true;
        }
    }
}

